/************************************************************************************
* PlayerWidget.cpp                                                                  *
*                                                                                   *
* Copyright (C) 2011 Varuna L Amachi                                                *
*                                                                                   *
* This program is free software; you can redistribute it and/or modify              *
* it under the terms of the GNU General Public License as published by              *
* the Free Software Foundation; either version 2 of the License, or any             *
* later version.                                                                    *
*                                                                                   *
* This program is distributed in the hope that it will be useful, but               *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY        *
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for       *
* more details. You should have received a copy of the GNU General Public           *
* License along with this program; if not, write to the Free Software Foundation,   *
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                       *
*                                                                                   *
*************************************************************************************/

#include <QtGui>
#include <algorithm>

#include "PlayerWidget.h"
#include "PlayerWidget.h"
#include "common/SizeConstants.h"
#include "common/Utils.h"
#include "common/Constants.h"

PlayerWidget::PlayerWidget(QWidget* parent) :
    QWidget(parent) {
    this->setObjectName("yamp");
    m_audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
    m_mediaObject = new Phonon::MediaObject(this);

    m_mediaObject->setTickInterval(1000);
    m_source = NULL;
    Phonon::createPath(m_mediaObject, m_audioOutput);

    setupActions();
    setupUi();
    setupStyle();

    connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
            this, SLOT(stateChanged(Phonon::State,Phonon::State)));
    connect(m_mediaObject, SIGNAL(tick(qint64)), m_infoArea, SLOT(tick(qint64)));
    connect(m_mediaObject, SIGNAL(aboutToFinish()), this, SLOT(notifyPlayFinished()));
    connect(m_mediaObject, SIGNAL(finished()), this, SIGNAL(finished()));
    connect(m_yampButton, SIGNAL(toggled(bool)), this, SIGNAL(yampSolo(bool)));
    connect(m_infoArea, SIGNAL(ratingChanged(MediaRating)), this,
            SLOT(notifyRatingChanged(MediaRating)));

}


void PlayerWidget::stateChanged(Phonon::State newState, Phonon::State oldState) {
    switch (newState) {
        case Phonon::ErrorState:
            if (m_mediaObject->errorType() == Phonon::FatalError) {
                QMessageBox::warning(this, tr("Fatal Error"),
                m_mediaObject->errorString());
            } else {
                QMessageBox::warning(this, tr("Error"),
                m_mediaObject->errorString());
            }
            break;
        case Phonon::PlayingState:
                m_playAction->setEnabled(false);
                m_playAction->setVisible(false);
                m_pauseAction->setVisible(true);
                m_pauseAction->setEnabled(true);
                m_stopAction->setEnabled(true);
                break;
        case Phonon::StoppedState:
                m_stopAction->setEnabled(false);
                m_playAction->setEnabled(true);
                m_playAction->setVisible(true);
                m_pauseAction->setEnabled(false);
                m_pauseAction->setVisible(false);
                break;
        case Phonon::PausedState:
                m_pauseAction->setEnabled(false);
                m_pauseAction->setVisible(false);
                m_stopAction->setEnabled(true);
                m_playAction->setEnabled(true);
                m_playAction->setVisible(true);
                break;
        case Phonon::BufferingState:
                break;
        default: ;
    }
    emit playerStateChanged(newState, oldState);
}


Phonon::State PlayerWidget::state() {
    return m_mediaObject->state();
}


void PlayerWidget::setSource(MediaItem* source) {
    if (source != NULL) {
        m_source = source;
        if(m_mediaObject->state() == Phonon::PlayingState) {
            m_mediaObject->stop();
            m_mediaObject->clearQueue();
        }
        m_mediaObject->setCurrentSource(*m_source->source());
        updateMediaInfo();
        m_mediaObject->play();
        notifyPlayStarted();
    }
}


void PlayerWidget::stopAndClear() {
        m_mediaObject->stop();
        m_mediaObject->clearQueue();
        m_mediaObject->clear();
//        m_mediaObject->setCurrentSource(NULL);
        m_infoArea->reset();
        m_playAction->setEnabled(false);
}



void PlayerWidget::setupActions() {
    m_previousAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipBackward), tr("Previous"), this);
    m_previousAction->setShortcut(tr("Ctrl+Z"));

    m_playAction = new QAction(style()->standardIcon(QStyle::SP_MediaPlay), tr("Play"), this);
    m_playAction->setShortcut(tr("Ctrl+X"));
    m_playAction->setDisabled(true);

    m_pauseAction = new QAction(style()->standardIcon(QStyle::SP_MediaPause), tr("Pause"), this);
    m_pauseAction->setShortcut(tr("Ctrl+C"));
    m_pauseAction->setDisabled(true);

    m_stopAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop), tr("Stop"), this);
    m_stopAction->setShortcut(tr("Ctrl+V"));
    m_stopAction->setDisabled(true);

    m_nextAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipForward), tr("Next"), this);
    m_nextAction->setShortcut(tr("Ctrl+B"));

    connect(m_playAction, SIGNAL(triggered()), m_mediaObject, SLOT(play()));
    connect(m_pauseAction, SIGNAL(triggered()), m_mediaObject, SLOT(pause()) );
    connect(m_stopAction, SIGNAL(triggered()), m_mediaObject, SLOT(stop()));
    connect(m_nextAction, SIGNAL(triggered()), this, SIGNAL(nextClicked()));
    connect(m_previousAction, SIGNAL(triggered()), this, SIGNAL(prevClicked()));

    m_pauseAction->setVisible(false);
    m_nextAction->setEnabled(false);
    m_previousAction->setEnabled(false);

}


void PlayerWidget::setupUi() {

    QToolBar *bar = new QToolBar(this);
    bar->addAction(m_previousAction);
    bar->addAction(m_playAction);
    bar->addAction(m_pauseAction);
    bar->addAction(m_stopAction);
    bar->addAction(m_nextAction);
    bar->setIconSize(QSize(32, 32));

    m_volumeSlider = new Phonon::VolumeSlider(this);
    m_infoArea = new SongInfoDisplayWidget(this);
    m_seekSlider = new Phonon::SeekSlider(this);
    m_yampButton  = new QPushButton(QIcon(":/yamp"), "", this);
    bar->setObjectName("yampcom");

//    m_volumeSlider->setObjectName("yampcomp");
//    m_infoArea->setObjectName("yampcomp");
//    m_seekSlider->setObjectName("yampcomp");
//    m_yampButton->setObjectName("yampcomp");
//    m_seekSlider->show();

    m_seekSlider->setMediaObject(m_mediaObject);
    m_volumeSlider->setAudioOutput(m_audioOutput);
    m_volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
    m_yampButton->setCheckable(true);
    m_yampButton->setChecked(true);

    QLabel *volumeLabel = new QLabel;
    volumeLabel->setPixmap(QPixmap("images/volume.png"));

    QHBoxLayout *seekerLayout = new QHBoxLayout;
    seekerLayout->addWidget(m_seekSlider);

    QHBoxLayout *playbackLayout = new QHBoxLayout;
    playbackLayout->addWidget(bar, 0, Qt::AlignCenter);
    playbackLayout->addStretch();
    playbackLayout->addWidget(volumeLabel);
    playbackLayout->addWidget(m_volumeSlider);
    playbackLayout->addWidget(m_yampButton);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(m_infoArea);
    mainLayout->addLayout(seekerLayout);
    mainLayout->addLayout(playbackLayout);
    setLayout(mainLayout);
    setAcceptDrops(true);
}



void PlayerWidget::setupStyle() {
    QPalette trans;
    trans.setColor(QPalette::Window, Qt::transparent);
    trans.setColor(QPalette::Text, Qt::green);
    QObjectList children = this->children();
    for(int i = 0; i < children.size(); i++) {
        if(children.at(i)->isWidgetType()) {
            QWidget* widget = qobject_cast<QWidget*>(children.at(i));
            widget->setAutoFillBackground(true);
            widget->setPalette(trans);
        }
    }

    QPalette playerBg;
    playerBg.setBrush(QPalette::Window, QBrush(QImage(":/player"))); //<<Set>>
    this->setAutoFillBackground(true);
    this->setPalette(playerBg);

    QPalette yampButtonBg;
    yampButtonBg.setColor(QPalette::Button, Qt::transparent);
    m_yampButton->setAutoFillBackground(true);
    m_yampButton->setPalette(yampButtonBg);
}


void PlayerWidget::setPlayEnabled(bool value) {
    m_playAction->setEnabled(value);
}

void PlayerWidget::setStopEnabled(bool value) {
    m_stopAction->setEnabled(value);
}

void PlayerWidget::setPrevEnabled(bool value) {
    m_previousAction->setEnabled(value);
}

void PlayerWidget::setNextEnabled(bool value) {
    m_nextAction->setEnabled(value);
}


void PlayerWidget::updateMediaInfo() {
    m_infoArea->setItem(m_source);
}

bool PlayerWidget::isPlayEnabled() {
    return m_playAction->isEnabled();
}

bool PlayerWidget::isStopEnabled() {
    return m_stopAction->isEnabled();
}

bool PlayerWidget::isPrevEnabled() {
    return m_previousAction->isEnabled();
}

bool PlayerWidget::isNextEnabled() {
    return m_nextAction->isEnabled();
}


void PlayerWidget::seekForword() {
    if(m_mediaObject->state() == Phonon::PlayingState) {
        quint64 seekOffset = Utils::min(m_mediaObject->remainingTime(), quint64(10000));
        m_mediaObject->seek(m_mediaObject->currentTime() + seekOffset);
    }
}


void PlayerWidget::seekBackword() {
    if(m_mediaObject->state() == Phonon::PlayingState) {
        quint64 seekOffset = Utils::min(m_mediaObject->currentTime(), quint64(10000));
        m_mediaObject->seek(m_mediaObject->currentTime() - seekOffset);
    }
}



void PlayerWidget::notifyPlayFinished() {
    foreach(IPlayerListener* lis, m_listeners) {
        lis->finished(m_source);
    }
}

void PlayerWidget::notifyPlayStarted() {
    foreach(IPlayerListener* lis, m_listeners) {
        lis->playStarted(m_source);
    }
}


void PlayerWidget::notifyRatingChanged(MediaRating rating) {
    foreach(IPlayerListener* lis, m_listeners) {
        lis->ratingChanged(m_source, rating);
    }
}

void PlayerWidget::addListener(IPlayerListener *listener) {
    m_listeners.append(listener);
}

PlayerWidget::~PlayerWidget() {
    m_listeners.clear();
}


void PlayerWidget::dragEnterEvent(QDragEnterEvent * event) {
    if(event->mimeData()->hasFormat("text/uri-list")) {
        event->acceptProposedAction();
    }
}


void PlayerWidget::dropEvent(QDropEvent *event) {
    contentDropped(event->mimeData()->urls());
}


void PlayerWidget::currentItemChanged(MediaItem *item) {
    m_infoArea->refresh();
}


MediaItem* PlayerWidget::currentTrack() {
    return m_source;
}
